package quiver.qgraph;



//import javafx.application.Application;
//import javafx.event.ActionEvent;
//import javafx.event.EventHandler;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.Scene;
//import javafx.scene.control.Button;
//import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.scene.chart.*;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.layout.RowConstraints;
class PlotData
{	
	LinkedList<Series<Number,Number>> seriesArch;
	LinkedList<String> label;
	LinkedList<String> color;
	LinkedList<String> lineStyle;
	PlotData()
	{
		seriesArch = new LinkedList<Series<Number,Number>>();
		label = new LinkedList<String>();
		color = new LinkedList<String>();
		lineStyle = new LinkedList<String>();
	}
}
public class QgraphExt //extends Application 
{
	private int xlength;
	private int ylength;
	private int plotNumber;
	private int rows;
	private int cols;
	private LinkedList<String> xLabel;
	private LinkedList<String> yLabel;
	private LinkedList<String> title;
	private LinkedList<PlotData> pdata;
	//private LinkedList<String> label;
	private GridPane gridpane;
	//private List<LineChart> linechart;
	//private LinkedList<Series> seriesArch;
	private boolean partitioned;
	private String labelBuff;
	//private NumberAxis[] xAxisArray;
    //private NumberAxis[] yAxisArray;
    /**
     * No argument constructor
     */
    public QgraphExt()
    {
    	xlength=0;
    	ylength=0;
    	plotNumber=1;
    	rows=1;
    	cols=1;
    	xLabel = new LinkedList<String>();
    	yLabel = new LinkedList<String>();
    	title = new LinkedList<String>();
    	//label = new LinkedList<String>();
    	//seriesArch = new LinkedList<Series>();
    	pdata = new LinkedList<PlotData>();
        partitioned = false;    
        gridpane = new GridPane();
    	
    }
    /**
     * constructor with dimensions as params
     * @param xdim
     * @param ydim
     */
    public QgraphExt(int xdim,int ydim)
    {
    	xlength = xdim;
    	ylength = ydim;
    	plotNumber=1;
    	rows=1;
    	cols=1;
    	xLabel = new LinkedList<String>();
    	yLabel = new LinkedList<String>();
    	title = new LinkedList<String>();
    	//label = new LinkedList<String>();
    	//seriesArch = new LinkedList<Series>();
    	pdata = new LinkedList<PlotData>();
        partitioned = false;
    }
    /**
     * setter function to set the dimention    
     * @param xdim
     * @param ydim
     */
    public void SetDimensions(int xdim,int ydim)
    {
    	xlength = xdim;
    	ylength = ydim;
    }
    private int[] PlotNumberDecode(int plotNumber)
    {
    	System.out.println("in : "+plotNumber+" x,y : "+cols+","+rows);
    	int[] XY = new int[2];
    	XY[1] = (int) Math.ceil((float)plotNumber/(float)cols)-1;  
    	XY[0] = plotNumber%cols;
    	if(XY[0] == 0)
    		XY[0] = cols-1;
    	else
    		XY[0] -=1;
    	System.out.println("returning x and y as : "+XY[0]+","+XY[1]);
    	return XY;
    }
    public void Subplot(int cols,int rows, int plotNumber)
    {
    	if(cols<1 || rows <1)
    	{
    		throw new InvalidSubplotSize("Invalid column or row size");
    	}
    	this.cols = cols;
    	this.rows = rows;
    	this.plotNumber = plotNumber;
    	if(!partitioned)
        {
    	gridpane = new GridPane();
    	gridpane.setHgap(0);    
        gridpane.setVgap(0);
        gridpane.setGridLinesVisible(true);
        gridpane.setMinSize(xlength, ylength);
        gridpane.setMaxSize(xlength, ylength);
        
        
        for(int i = 0;i<cols;i++)
        {
        	ColumnConstraints col = new ColumnConstraints();
        	col.setPercentWidth(Math.floor(100/(cols)));
        	gridpane.getColumnConstraints().add(col);        	
        }
        for(int i = 0;i<rows;i++)
        {        	
        	RowConstraints row = new RowConstraints();
        	row.setPercentHeight(Math.floor(100/(rows)));        	
        	gridpane.getRowConstraints().add(row);        	
        }
        for(int i = 0; i<cols*rows;i++)
        {
        	xLabel.add(" ");
        	yLabel.add(" ");
        	//label.add("");
        	pdata.add(new PlotData());
        	title.add(" ");
        }
        partitioned = true;
        }
        /*
       for(int i=0;i<cols*rows;i++)
       {
    	   NumberAxis xAxis = new NumberAxis();
           NumberAxis yAxis = new NumberAxis();
    	   LineChart<Number,Number> lcrt = new LineChart<Number,Number>(xAxis,yAxis);    	   
    	   linechart.add(lcrt);
    	   int xy[] = PlotNumberDecode(i+1);
    	   gridpane.add(lcrt,xy[0],xy[1]);
    	   System.out.println("ID of line chart is : "+lcrt.getId());
    	   System.out.println("ID of gridpane is : "+gridpane.getId());
    	   System.out.println("ID of xaxis chart is : "+xAxis.getId());
    	   System.out.println("ID of yaxis chart is : "+yAxis.getId());
       }
       */
        System.out.println("done with constructor");
    }/*
    public void Subplot(int cols, int rows, int currentPlot)
    {    	
    	if(cols<1 || rows <1)
    	{
    		throw new InvalidSubplotSize("Invalid column or row size");
    	}
    	if(currentPlot>cols*rows || currentPlot<=0)
    	{
    		throw new InvalidCurrentPlot("Invalid index "+currentPlot+" in "+cols+" x "+rows);
    	}
    	this.cols = cols;
    	this.rows = rows;
    	this.plotNumber = currentPlot;
    	
    	//		xAxisArray[i+j] = new NumberAxis();
    	  //  	yAxisArray[i+j] = new NumberAxis();
    	
    }
    */
    public void XLabel(String s)
    {   
    	xLabel.set(plotNumber-1, s);
    	
    }
    public void YLabel(String s)
    {       	
    	yLabel.set(plotNumber-1, s);
    }
    public void Title(String s)
    {
    	xLabel.set(plotNumber-1, s);
    }
    public void Label(String s)
    {
    	//label.set(plotNumber-1, label.get(plotNumber)+s+"~");
    	labelBuff = s;
    	    	
    }
    public void Plot(Stage stage,int [] xVals,int[] yVals) {
    	Plot(stage,xVals,yVals,"-","#0000FF");
    }
	public void Plot(Stage stage,int [] xVals,int[] yVals,String lineStyle, String color) {                    
        
		NumberAxis xAxis = new NumberAxis();
        NumberAxis yAxis = new NumberAxis();
        System.out.println("In Plot()");
        
        xAxis.setLabel(xLabel.get(plotNumber-1));
        yAxis.setLabel(yLabel.get(plotNumber-1));
        
        LineChart<Number,Number> lcrt = new LineChart<Number,Number>(xAxis,yAxis);
        lcrt.setTitle(title.get(plotNumber-1));
        Series<Number, Number> series = new XYChart.Series<>();
        
        for(int i = 0 ;i<xVals.length;i++)
        {
        	series.getData().add(new XYChart.Data<Number,Number>(xVals[i],yVals[i]));
        }       
        
        pdata.get(plotNumber-1).seriesArch.add(series);
        pdata.get(plotNumber-1).color.add(color);//"#0000FF" 
        pdata.get(plotNumber-1).label.add(labelBuff);
        pdata.get(plotNumber-1).lineStyle.add(lineStyle);
        
        lcrt.getData().addAll(pdata.get(plotNumber-1).seriesArch);
        
        System.out.println("adding grid pane"+plotNumber);
        int XY[] = PlotNumberDecode(plotNumber);
       // GridPane gridpane = new GridPane(); 
        gridpane.add(lcrt, XY[0], XY[1]);              
        
        Pane layout = new Pane();
        layout.getChildren().clear();        
        layout.getChildren().addAll(gridpane);        
        stage.setScene(new Scene(layout,xlength,ylength));
        System.out.println("done with everything");
      
        for(int i = 0;i<pdata.get(plotNumber-1).lineStyle.size();i++)
        {
        Node n2 = lcrt.lookup(".series"+i);
        StringBuilder style = MakeStyle(pdata.get(plotNumber-1).color.get(i),pdata.get(plotNumber-1).lineStyle.get(i));      
        n2.setStyle(style.toString());
        }
        lcrt.setCreateSymbols(false);
        
        stage.show();
    }
	private StringBuilder MakeStyle(String color,String lineStyle)
	{
		/*
		 * 
		 */
		/*
		 StringBuilder style = new StringBuilder();
		 style.append(".chart-series-line { \n");
		 style.append("-fx-stroke-width: 1; -fx-stroke: gray;-fx-stroke-dash-array: 6 6;\n");
		 style.append("}");
		 style.append(".thick-chart .chart-series-line { \n");    
		 style.append(" -fx-stroke-width: 1px;\n");
		 style.append("}");
		 return style;
		 */
		String lStyle = new String();
		if(lineStyle.equals("--"))
			lStyle = "6 6";
		else if(lineStyle.equals("-"))
			lStyle = "1";
		else if(lineStyle.equals(":"))
			lStyle = "2 2";
		else if(lineStyle.equals("-."))
			lStyle = "24 3 6 3";
		else
			lStyle = "1";
				
		System.out.println("color : "+color+"  line style : "+lStyle);
		StringBuilder style = new StringBuilder();
		style.append("-fx-stroke: ").append(color).append("; -fx-background-color: ").append(color).append(", white; ");
        style.append("-fx-stroke-width: 1; -fx-stroke-dash-array: ").append(lStyle).append(";");   
		return style;
	}
}
class InvalidCurrentPlot extends RuntimeException
{
	private static final long serialVersionUID = -3311785315235210132L;
	InvalidCurrentPlot(String s)
	{
		super(s);
	}
}
class InvalidSubplotSize extends RuntimeException
{
	private static final long serialVersionUID = -3311785315235210133L;
	InvalidSubplotSize(String s)
	{
		super(s);
	}
}